#include <8052.h>

//https://blog.csdn.net/lllwwwppp/article/details/108320115
#include "IRReceiver.h"

unsigned char IRReceiver_Time;      //储存检测红外高低电平持续时间
unsigned char IRReceiver_Record[4]; //储存解码后的4个字节数据
unsigned char IRReceiver_Data[33];  //包含起始码在内的33位数据
__bit IRReceiver_Deal_OK;           //解码后4个字节数据接收完成标志位
__bit IRReceiver_OK;                //33位数据接收完成标志

void IRReceiver_Init()
{

    TMOD |= 0x02; //设置定时器0工作模式2,8位自动重装
    //8位自动重装载定时器，当溢出时将TH0存放的值自动重装入TL0
    TL0 = TH0 = 0; //初始化定时器0寄存器，定时器0溢出一次时间为256个机器周期
    ET0 = 1;       //开定时器0中断
    TR0 = 1;       //启动定时器0

    //外部中断0
    IT0 = 1; //设置外部中断0跳变沿触发方式
    EX0 = 1; //开外部中断0中断

    // TMOD |= 0x20;     //设置定时器1工作模式2 ,8位自动重装
    // TL1 = TH1 = 0xfd; //比特率9600
    // SM1 = 1;          //设置串口工作模式1,10位异步收发
    // TR1 = 1;          //启动定时器1

    EA = 1; //开总中断
}

void IRReceiver_Delay300ms() //@11.0592MHz
{
    unsigned char i, j, k;
    i = 3;
    j = 26;
    k = 23;
    do
    {
        do
        {
            while (--k)
                ;
        } while (--j);
    } while (--i);
}

//定时器0中断，每中断一次需要256*1.085us =  277.76us
void IRReceiver_Time0() __interrupt 1
{
    IRReceiver_Time++; //277.76us
}

//外部中断0, 存入33次脉宽
void IRReceiver_Int0() __interrupt 0
{
    static unsigned char i; //静态变量用于存入33次数据计数
    static __bit startflag; //开始储存脉宽标志位
    if (startflag)
    {
        /*判断引导码，如果是引导码则从起始码开始存*/
        if ((IRReceiver_Time < 53) && (IRReceiver_Time >= 32))
            i = 0;
        IRReceiver_Data[i] = IRReceiver_Time; //以TO溢出的次数来计算脉宽把这个时间存放在数组中
        IRReceiver_Time = 0;                  //计数清零
        i++;                                  //计数脉宽存入次数自加
        if (i == 33)                          //i等于33那么就表示已经存入了33次脉宽
        {
            IRReceiver_OK = 1; //脉宽检查完成
            i = 0;             //把脉宽计数清零准备下次存入
        }
    }
    else
    {
        IRReceiver_Time = 0; //定时器0计数清零
        startflag = 1;       //开始处理标志位置1
    }
}

//把提取的33次脉宽进行解码 NEC协议
void IRReceiver_DealData()
{
    unsigned char i; //i是用于计数处理4个字节
    unsigned char j; //j用于计数处理1个字节的8位数据
    unsigned char k; //k用于计数处理33次脉宽
    k = 1;           //从第一位脉宽开始处理，丢掉起始码
    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 8; j++)
        {
            //如果脉宽大于数据0标准的1125us那么就判定为数据1
            if (IRReceiver_Data[k] > 5)
                IRReceiver_Record[i] |= 0x80; //写1
            //只能右移7次，如果右移8次则会把第一位数据移出去
            if (j < 7)
                IRReceiver_Record[i] >>= 1;
            k++; //处理下一次脉宽
        }
    }
    IRReceiver_Deal_OK = 1; //解码完成
}


void IRReceiver_Test(fun_callback fcallback)
{
    unsigned char i;   //计数串口发送字节数
    IRReceiver_Init(); //初始化
    while (1)
    {
        if (IRReceiver_OK) //判断33次脉宽是否提取完成
        {
            IRReceiver_DealData();  //根据脉宽解码出4个字节的数据
            IRReceiver_OK = 0;      //清零脉宽检查完成标志位等待下一次脉宽检查
            if (IRReceiver_Deal_OK) //判断解码是否完成
            {
                for (i = 0; i < 4; i++) //串口发送4个字节数据
                {
                    SBUF = IRReceiver_Record[i]; //发送数据
                    while (!TI)
                        ;   //等待发送完成标志
                    TI = 0; //清零发送完成标志位
                }
                IRReceiver_Deal_OK = 0; //清零解码标志位

                if (IRReceiver_Record[2] = ~IRReceiver_Record[3])
                {
                    // P1 = IRReceiver_Record[2];
                    // //P2_3为蜂鸣器
                    // P2_3 = 0; //开启
                    // IRReceiver_Delay300ms();
                    // P2_3 = 1;
                    // P1 = IRReceiver_Record[3];
                    if (fcallback)
                    {
                        fcallback(IRReceiver_Record[2]);
                    }

                    //检测出来的编码 IRReceiver_Record[2]
                    //1:    0b01000100
                    //2:    0b01000110
                    //3:    0b01000110
                    //4:    0b01000100
                    //5:    0b01000000
                    //6:    0b01000010
                    //7:    0b00000110
                    //8:    0b00010100
                    //9:    0b00001000
                    //0:    0b00011000
                    //*:    0b00010110
                    //#:    0b00001100
                    //上：  0b00011000
                    //下：  0b01010010
                    //左：  0b00001000
                    //右：  0b01011010
                    //ok:   0b00011100
                }
            }
        }
    }
}